var userTable = document.getElementById("onlineUser");
var msgArea = document.getElementById("msgArea");
var uploadImg = document.getElementById("uploadImg");
var textarea = document.getElementById("input");
var btnSend = document.getElementById("send");
var previewDialog = document.getElementById("previewDialog");
var previewImg = document.getElementById("previewImg");
var historyDialog = document.getElementById("historyDialog");
var pre = document.getElementsByTagName("pre")[0]
var historyUser = document.getElementById("historyUser");
var keyword = document.getElementById("keyword");
var btnSearch = document.getElementById("btnSearch");
var historyDate = document.getElementById("historyDate");
window.addEventListener("loadend", fnInit());

/**
 * 页面初始化
 */
function fnInit() {

    //以下处理websocekt
    const socket = new WebSocket("ws://" + location.host + "/ws");
    socket.addEventListener("open", e => {});
    socket.addEventListener("message", e => { //接收到服务端推送
        let decoded = decodeURIComponent(e.data); //先解码
        let data = eval(decoded.replace(/\n/g, "\\n")); //关于加号、空格、换行的编解码冲突问题的折衷解决
        switch (data.msgType) {
            case "refreshOnlineUser": //刷新在线用户（可能是出现了新的上线下线）
                refreshOnlineUser(data.datas);
                break;
            case "spreadMsg": //接收新消息
                receiveMsg(data.datas);
                break;
            case "location": //接受重定向
                if (data.datas.note) {
                    alert(data.datas.note);
                }
                location.href = "http://" + location.host + data.datas.url;
                break;
            default:
                console.log(data);
                alert("ws错误：未知的消息类型！");
        }
    });

    fnInitDialog();
}

/**
 * 初始化预览图片及聊天记录dialog面板
 */
function fnInitDialog() {
    document.getElementById("input").addEventListener("paste", e => { //监控浏览器内复制粘贴
        let items = e.clipboardData.items;
        for (let i in items) {
            if (items[i].type && items[i].type.indexOf("image/") > -1) { //判定图片
                fnPreviewImg(items[i].getAsFile(), true);
            }
        }
    });

    previewDialog.addEventListener("cancel", e => { //按esc关闭图片dialog
        uploadImg.value = "";
        previewDialog.removeAttribute("transform");
    });
    historyDialog.addEventListener("cancel", e => { //按esc关闭聊天记录dialog
        historyDialog.removeAttribute("transform");
    });

    fnQueryUsers(users => { //初始化用户下拉
        let historyUsers = document.getElementById("historyUsers");
        for (let i in users) {
            let option = document.createElement("option");
            let user = decodeURIComponent(users[i]);
            option.value = user;
            option.innerHTML = user;
            historyUsers.appendChild(option);
        }
    });
    var now = new Date();
    historyDate.valueAsNumber = now.getTime() - now.getTimezoneOffset() * 60000; //初始化日期条件

    //以下为弹出 dialog 运用 h5 drag 实现面板自由拖动
    var innerX, innerY;
    pre.addEventListener("mousedown", e => {
        historyDialog.draggable = false;
    });
    pre.addEventListener("blur", e => { //屏蔽掉聊天历史记录区域的拖动，不然没法框选消息文本了
        historyDialog.draggable = true;
    });
    previewDialog.addEventListener("dragstart", e => { //记录鼠标位置
        innerX = e.offsetX;
        innerY = e.offsetY;
    });
    historyDialog.addEventListener("dragstart", e => { //屏蔽掉有正常点击拖选操作的组件
        if ([historyUser, keyword].indexOf(document.activeElement) > -1) {
            e.preventDefault();
        } else {
            innerX = e.offsetX;
            innerY = e.offsetY;
        }
    });
    document.addEventListener("dragover", e => { //阻止默认的弹回
        e.preventDefault();
    });
    document.addEventListener("drop", e => { //更改默认的弹回为移至当前坐标
        if (previewDialog.open) {
            previewDialog.style.left = e.x - innerX + "px";
            previewDialog.style.top = e.y - innerY + "px";
            e.preventDefault();
        }
        if (historyDialog.open) {
            historyDialog.style.left = e.x - innerX + "px";
            historyDialog.style.top = e.y - innerY + "px";
            e.preventDefault();
        }
    });
}

/**
 * 刷新在线用户
 * 
 * @param {json} datas 用户信息json数组
 */
function refreshOnlineUser(datas) {
    let rowCount = userTable.rows.length - 1;
    for (let i = rowCount; i > 0; i--) { //清空非th行
        userTable.deleteRow(i);
    }
    datas.sort((o1, o2) => { //保证自己排在第一
        return o1.isSelf - o2.isSelf;
    });
    for (let i in datas) { //重新生成所有td
        let data = datas[i];
        let cell = userTable.insertRow(1).insertCell(0);
        cell.innerHTML = "<div" + (data.isSelf ? " class='selfUser' " : "") + ">" +
            "<img src='" + data.icon + "' />" +
            data.username + "</div>";
    }
}

/**
 * 接收新聊天消息
 * 
 * @param {json} datas 消息json对象
 */
function receiveMsg(datas) {
    fnCreateMsg(datas.isSelf, datas.username, datas.icon, datas.timestamp.substring(11, 19), datas.isImg, datas.color, datas.fontSize, datas.msg);
    fnInsertHistory({ //可能出现中文的编码再存，避免IndexedDB出问题，其中date为专供查询的冗余字段，另IndexedDB不支持boolean
        timestamp: datas.timestamp,
        username: encodeURIComponent(datas.username),
        date: datas.timestamp.substring(0, 10),
        isImg: datas.isImg + "",
        msg: encodeURIComponent(datas.msg)
    });
}

/**
 * 发送新聊天消息
 */
function fnSendText() {
    if (textarea.value.length == 0) {
        return;
    }
    btnSend.disabled;
    fnAjax("POST", "/sendMsg", "msg=" + textarea.value + "&color=" + document.getElementById("color").value + "&fontSize=" + document.getElementById("fontSize").value, () => {
        btnSend.removeAttribute("disabled");
        textarea.value = "";
        textarea.focus();
    }, () => {
        btnSend.removeAttribute("disabled");
    });
}

/**
 * 渲染新聊天消息
 * 
 * @param {boolean} isSelf 是否为自己所发
 * @param {string} username 用户名
 * @param {string} icon 头像
 * @param {string} time 日期时间的时分秒部分
 * @param {boolean} isImg 是否为图片消息
 * @param {string} color 字色
 * @param {string} fontSize 字号
 * @param {string} msg 消息内容，图片时为base64串
 */
function fnCreateMsg(isSelf, username, icon, time, isImg, color, fontSize, msg) {
    let msgDiv = document.createElement("div");
    msgArea.firstElementChild.appendChild(msgDiv);
    if (isSelf) {
        msgDiv.classList.add("selfMsg");
    }
    msgDiv.innerHTML = (isSelf ? time + " " + username : username + " " + time) + "<div>\r\n" +
        "<img class='icon' src='" + icon + "'></img>\r\n" +
        (isImg ? "<div><div class='msgImgDiv'><img src='" + msg + "'></img></div></div>" : "<label style='color:" + color + ";font-size:" + fontSize + ";'>" + msg + "</label>") + "\r\n" +
        "</div>";
    msgArea.lastElementChild.lastElementChild.scrollIntoView();
}

/**
 * 改变字色
 * 
 * @param {string} color 颜色值
 */
function fnChangeColor(color) {
    textarea.style.color = color;
}

/**
 * 改变字号
 * 
 * @param {string} fontSize 字号
 */
function fnChangeFontSize(fontSize) {
    textarea.style.fontSize = fontSize + "px";
}

/**
 * 预览图片
 * 
 * @param {File} file 图片文件
 * @param {boolean} isPaste 是否来自浏览器内粘贴
 */
function fnPreviewImg(file, isPaste) {
    if (isPaste) {
        let fr = new FileReader();
        fr.onloadend = () => previewImg.src = fr.result;
        fr.readAsDataURL(file);
    } else {
        fnShowImg(file, previewImg);
    }
    previewDialog.showModal(); //显示图片dialog元素，展现简单的动画
    previewDialog.style.left = (innerWidth - previewDialog.clientWidth) / 2 + "px";
    previewDialog.setAttribute("transform", null);
}

/**
 * 确认发送图片
 */
function sendImg() {
    fnAjax("POST", "/sendMsg", "isImg=true&msg=" + previewImg.src);
    previewDialog.close();
    uploadImg.value = "";
}

/**
 * 弹出聊天记录dialog
 */
function fnHistory() {
    historyDialog.showModal();
    fnSearch();
    historyDialog.style.left = (innerWidth - historyDialog.clientWidth) / 2 + "px";
    historyDialog.setAttribute("transform", null);
}

/**
 * 聊天记录面板切换 全部/图片
 * 
 * @param {boolean} enbale 设置关键字项是否可用
 */
function fnEnableKeword(enbale) {
    if (enbale) {
        keyword.removeAttribute("readonly");
        btnSearch.removeAttribute("readonly");
    } else {
        keyword.value = "";
        keyword.setAttribute("readonly", true);
        btnSearch.setAttribute("readonly", true);
    }
}

/**
 * 查询聊天记录
 */
function fnSearch() {
    btnSearch.setAttribute("disabled", true);
    let progress = document.getElementsByTagName("progress")[0];
    if (keyword.value) {
        progress.style.visibility = "visible";
    }
    fnQueryHistory(historyDate.value, encodeURIComponent(historyUser.value) || null, document.querySelector("[name=onlyImg]:checked").value, resultSet => {
        let tmp = setInterval(function () {
            if (_filter.next().done) {
                clearInterval(tmp);
                btnSearch.removeAttribute("disabled");
            }
        }, 1);
        let _filter = function* () { //关键字模糊查询无法在IndexedDB内结合多条件组合查询实现，改为先以其它条件查出结果集，再js处理，因而借由generator增加了动画过程
            let username = fnGetCookieJson().username;
            let html = "";
            let day;
            let re = new RegExp(keyword.value);
            for (let i = 0, l = resultSet.length; i < l; i++) { //遍历结果集
                yield;
                let rowData = resultSet[i];
                let msg = decodeURIComponent(rowData.msg); //注意解码
                if (keyword.value) { //关键字过滤
                    progress.value = i * 100 / l;
                    if (rowData.isImg == "true" || msg.indexOf(keyword.value) == -1) {
                        continue;
                    }
                }
                if (rowData.date != day) {
                    if (day) { //查询结果跨天时，新的一天产生一个隔断及日期title，高仿qq
                        html += "<svg><line x1='0' y1='25' x2='320' y2='25'/></svg><span class='dateLine'>" + rowData.date;
                        html += "</span><svg><line x1='10' y1='25' x2='330' y2='25'/></svg>\r\n";
                    }
                    day = rowData.date;
                }
                html += "<span" + (rowData.username == username ? " class='selfMsg' " : "") + ">" + decodeURIComponent(rowData.username) + " " +
                    rowData.timestamp.substring(0, 19) + "</span>\r\n";
                if (rowData.isImg == "true") { //图片时
                    html += "<img src='" + msg + "'/>";
                } else if (keyword.value) { //关键字高亮
                    html += msg.replace(re, "<mark>" + keyword.value + "</mark>");
                } else {
                    html += msg;
                }
                html += "\r\n";
            }
            pre.innerHTML = html;
            progress.style.visibility = "hidden";
        }.call();
    });
}

/**
 * 登出
 */
function fnExit() {
    fnAjax("GET", "/exit");
}